#include <jni.h>
#include "include/packet.h"
#include "include/unpack.h"
#include <string>

extern "C" jstring Java_com_kbtx_st0601_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}


extern "C" jobject Java_com_kbtx_st0601_KLV_unpackMisb(JNIEnv *env, jclass thiz, jbyteArray data, int length) {
    // TODO: implement unpackMisb()
    jbyte *cData = env->GetByteArrayElements(data, nullptr);
    auto klvMap = (pKLVMap)(calloc(1, sizeof(KLVMap)));
    unpack_misb((unsigned char *)cData, length, klvMap);


    // 获取 ArrayList 类
    jclass arrayListClass = env->FindClass("java/util/ArrayList");
    // 获取 ArrayList 构造函数
    jmethodID arrayListConstructor = env->GetMethodID(arrayListClass, "<init>", "()V");
    // 创建 ArrayList 对象
    jobject klvs = env->NewObject(arrayListClass, arrayListConstructor);
    // 获取 ArrayList 的 add 方法
    jmethodID arrayListAdd = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    // 获取 KLV 类
    jclass klvClass = env->FindClass( "com/kbtx/st0601/KLV");
    // 获取 KLV 构造函数
    jmethodID klvConstructor = env->GetMethodID( klvClass, "<init>", "(IILjava/lang/Object;)V");

    jclass byteCls = env->FindClass("java/lang/Byte");
    jmethodID byteCons = env->GetMethodID(byteCls, "<init>", "(B)V");

    jclass shortCls = env->FindClass("java/lang/Short");
    jmethodID shortCons = env->GetMethodID(shortCls, "<init>", "(S)V");

    jclass intCls = env->FindClass("java/lang/Integer");
    jmethodID intCons = env->GetMethodID(intCls, "<init>", "(I)V");

    jclass longCls = env->FindClass("java/lang/Long");
    jmethodID longCons = env->GetMethodID(longCls, "<init>", "(J)V");

    jclass floatCls = env->FindClass("java/lang/Float");
    jmethodID floatCons = env->GetMethodID(floatCls, "<init>", "(F)V");

    jclass doubleCls = env->FindClass("java/lang/Double");
    jmethodID doubleCons = env->GetMethodID(doubleCls, "<init>", "(D)V");

    // 创建 KLV 对象
    jobject value = nullptr; // 你的value值，这里假设为null
    for (const auto item: (*klvMap).KLVs) {
        if(item == nullptr) continue;
        switch (item->value.type){
            case UINT8:
                value = env->NewObject(byteCls, byteCons, item->value.int8_value);
                break;
            case UINT16:
                value = env->NewObject(shortCls, shortCons, item->value.int16_value);
                break;
            case UINT32:
                value = env->NewObject(intCls, intCons, item->value.int32_value);
                break;
            case UINT64:
                value = env->NewObject(longCls, longCons, item->value.int64_value);
                break;
            case INT8:
                value = env->NewObject(byteCls, byteCons, item->value.int8_value);
                break;
            case INT16:
                value = env->NewObject(shortCls, shortCons, item->value.int16_value);
                break;
            case INT32:
                value = env->NewObject(intCls, intCons, item->value.int32_value);
                break;
            case INT64:
                value = env->NewObject(longCls, longCons, item->value.int64_value);
                break;
            case CHAR_P:
                value = env->NewStringUTF(item->value.charp_value);
                break;
            case FLOAT:
                value = env->NewObject(floatCls, floatCons, item->value.float_value);
                break;
            case DOUBLE:
                value = env->NewObject(doubleCls, doubleCons, item->value.double_value);
                break;
            default :
                printf("value ???");
                break;
        }
        if(value != nullptr){
            jobject klvObject = env->NewObject(klvClass, klvConstructor, (int)item->tag, (int)item->size, value);
            env->CallBooleanMethod(klvs, arrayListAdd, klvObject);
        }
    }

    free(klvMap);

    return klvs;
}
extern "C" jbyteArray Java_com_kbtx_st0601_KLV_packMisb(JNIEnv *env, jclass thiz)  {
    // TODO: implement packMisb()
    pPacket packet = initialize_packet();
    char* name = "Mission01";
    GenericValue mission = {.type=CHAR_P, .charp_value=name};
    float slant_range = 26.12;
    GenericValue range = {.type=FLOAT, .float_value = slant_range};
    GenericValue doub = {.type=DOUBLE, .double_value = slant_range};
    GenericValue doub2 = {.type=DOUBLE, .double_value = slant_range};

// Add KLVs into packet
    packet = add_klv(packet, FieldMap[MISSION_ID], mission);
    packet = add_klv(packet, FieldMap[SLANT_RANGE], range);
    packet = add_klv(packet, FieldMap[CORNER_LATITUDE_POINT_1], doub);
    packet = add_klv(packet, FieldMap[CORNER_LONGITUDE_POINT_1], doub2);

// Finalize packet by adding checksum and total length
    finalize_packet(packet);
    jbyteArray result = env->NewByteArray(packet->size);
    jbyte* elements = env->GetByteArrayElements(result, nullptr);
    for(jsize i = 0; i < packet->size; i++){
        elements[i] = packet->content[i];
    }
    env->ReleaseByteArrayElements(result, elements, 0);
    free_packet(packet);

    return result;
}